package com.easychat.service.impl;

import com.easychat.common.LeaseException;
import com.easychat.common.Result;
import com.easychat.dto.MessageSendDto;
import com.easychat.dto.SysSettingDto;
import com.easychat.entity.*;
import com.easychat.entity.query.UserContactApplyQuery;
import com.easychat.entity.query.UserContactQuery;
import com.easychat.enums.*;
import com.easychat.mappers.*;
import com.easychat.redis.RedisComponent;
import com.easychat.service.UserContactApplyService;
import com.easychat.utils.StringTools;
import com.easychat.websocket.ChannelContextUtils;
import com.easychat.websocket.MessageHandler;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;

/**
 * (UserContactApply)表服务实现类
 *
 * @author makejava
 * @since 2024-10-08 20:03:16
 */
@Service("userContactApplyService")
public class UserContactApplyServiceImpl implements UserContactApplyService {
    @Resource
    private UserContactApplyDao userContactApplyDao;
    @Resource
    private UserContactDao userContactDao;
    @Resource
    private RedisComponent redisComponent;
    @Resource
    private ChatSessionDao chatSessionDao;
    @Resource
    private ChatSessionUserDao chatSessionUserDao;
    @Resource
    private UserInfoDao userInfoDao;
    @Resource
    private ChatMessageDao chatMessageDao;
    @Resource
    private MessageHandler messageHandler;
    @Resource
    private GroupInfoDao groupInfoDao;
    @Resource
    private ChannelContextUtils channelContextUtils;

    /**
     * 通过ID查询单条数据
     *
     * @param applyId 主键
     * @return 实例对象
     */
    @Override
    public UserContactApply queryById(Integer applyId) {
        return this.userContactApplyDao.queryById(applyId);
    }

    /**
     * 分页查询
     *
     * @param userContactApply 筛选条件
     * @param pageRequest      分页对象
     * @return 查询结果
     */
    @Override
    public Page<UserContactApply> queryByPage(UserContactApply userContactApply, PageRequest pageRequest) {
        long total = this.userContactApplyDao.count(userContactApply);
        return new PageImpl<>(this.userContactApplyDao.queryAllByLimit(userContactApply, pageRequest), pageRequest, total);
    }

    /**
     * 新增数据
     *
     * @param userContactApply 实例对象
     * @return 实例对象
     */
    @Override
    public UserContactApply insert(UserContactApply userContactApply) {
        this.userContactApplyDao.insert(userContactApply);
        return userContactApply;
    }

    /**
     * 修改数据
     *
     * @param userContactApply 实例对象
     * @return 实例对象
     */
    @Override
    public UserContactApply update(UserContactApply userContactApply,Integer applyId) {
        this.userContactApplyDao.update(userContactApply,applyId);
        return this.queryById(userContactApply.getApplyId());
    }

    /**
     * 通过主键删除数据
     *
     * @param applyId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer applyId) {
        return this.userContactApplyDao.deleteById(applyId) > 0;
    }

    @Override
    public Result<UserContactApply> selectByReceiveIdPage(PageRequest pageRequest, UserContactApplyQuery userContactApplyQuery) {
        PageHelper.startPage(pageRequest.getPageNumber(),pageRequest.getPageSize());
        PageHelper.orderBy("last_apply_time asc");
        UserContactApply userContactApply = userContactApplyDao.selectList(userContactApplyQuery);
        return null;
    }
    @Override
    public void dealWithApply(String userId, Integer applyId, Integer status) {
        UserContactApplyStatusEnum statusEnum = UserContactApplyStatusEnum.getByStatus(status);
        if(statusEnum == null || UserContactApplyStatusEnum.INIT == statusEnum){
            throw new LeaseException(ExceptionCodeEnum.ERROR_REQUEST);
        }
        UserContactApply applyInfo = userContactApplyDao.selectByApplyId(applyId);
        if(applyInfo == null || !userId.equals(applyInfo.getReceiveUserId())){
            throw new LeaseException(ExceptionCodeEnum.ERROR_REQUEST);
        }
        UserContactApply updateInfo = new UserContactApply();
        updateInfo.setStatus(statusEnum.getStatus());
        updateInfo.setLastApplyTime(System.currentTimeMillis());

        Integer count =userContactApplyDao.updateByParam(updateInfo,applyId,UserContactApplyStatusEnum.INIT.getStatus());
        if(count == 0){
            throw new LeaseException(ExceptionCodeEnum.ERROR_REQUEST);
        }
        if(UserContactApplyStatusEnum.PASS.getStatus().equals(status)){
            addContact(applyInfo.getApplyUserId(),applyInfo.getReceiveUserId(),applyInfo.getContactId(),applyInfo.getContactType(),applyInfo.getApplyInfo());

            return;
        }

        if(UserContactApplyStatusEnum.BLACKLIST == statusEnum){
            Date curDate = new Date();
            UserContact userContact = new UserContact();
            userContact.setUserId(applyInfo.getApplyUserId());
            userContact.setContactId(applyInfo.getContactId());
            userContact.setContactType(applyInfo.getContactType());
            userContact.setCreateTime(curDate);
            userContact.setStatus(UserContactApplyStatusEnum.BLACKLIST_BE.getStatus());
            userContact.setLastUpdateTime(curDate);
            Integer updateCount = userContactDao.insertOrUpdate(userContact);
        }

    }

    /**
     * 添加好友
     * @param applyUserId
     * @param receiveUserId
     * @param contactId
     * @param contactType
     * @param applyInfo
     */
    @Override
    public void addContact(String applyUserId, String receiveUserId, String contactId, Integer contactType,String applyInfo) {
            //群聊人数
        if(UserContactTypeEnum.GROUP.getType().equals(contactType)){
            Integer count = userContactDao.selectCount(contactId,1);
            SysSettingDto sysSetting = redisComponent.getSysSetting();
            if(count >= sysSetting.getMaxGroupMemberCount()){
                throw new LeaseException("需要升级超大会员，扩大群员数");
            }
        }
        Date curDate = new Date();
        //同意双方添加好友
        ArrayList<UserContact> contactArrayList = new ArrayList<>();
        //申请人添加对方
        UserContact userContact = new UserContact();
        userContact.setUserId(applyUserId);
        userContact.setContactId(contactId);
        userContact.setContactType(contactType);
        userContact.setStatus(1);
        userContact.setLastUpdateTime(curDate);
        userContact.setLastUpdateTime(curDate);
        contactArrayList.add(userContact);
        //如果是申请好友，接收人添加申请人，群组不用添加对方为好友
        if(UserContactTypeEnum.USER.getType().equals(contactType)){
            userContact = new UserContact();
            userContact.setUserId(receiveUserId);
            userContact.setContactId(applyUserId);
            userContact.setContactType(contactType);
            userContact.setCreateTime(curDate);
            userContact.setLastUpdateTime(curDate);
            userContact.setStatus(1);
            contactArrayList.add(userContact);
            redisComponent.addUserContact(receiveUserId,applyUserId);
        }
        //批量插入
        redisComponent.addUserContact(applyUserId,contactId);
        userContactDao.insertOrUpdateBatch(contactArrayList);

        //创建会话
        String sessionId = null;
        if(UserContactTypeEnum.USER.getType().equals(contactType)){
            sessionId = StringTools.getChatSessionId4User(new String[]{applyUserId,contactId});
        }else {
            sessionId = StringTools.getChatSessionId4Group(contactId);
        }
        ArrayList<ChatSessionUser> chatSessionUsers = new ArrayList<>();
        if(UserContactTypeEnum.USER.getType().equals(contactType)){
            //创建会话
            ChatSession chatSession = new ChatSession();
            chatSession.setSessionId(sessionId);
            chatSession.setLastMessage(applyInfo);
            chatSession.setLastReceiveTime(curDate.getTime());
            chatSessionDao.insertOrUpdate(chatSession);

            //申请人session
            ChatSessionUser applySessionUser = new ChatSessionUser();
            applySessionUser.setUserId(applyUserId);
            applySessionUser.setContactId(contactId);
            applySessionUser.setSessionId(sessionId);
            UserInfo contactUser = userInfoDao.queryById(contactId);
            applySessionUser.setContactName(contactUser.getNickName());
            chatSessionUsers.add(applySessionUser);

            //接收人session
            ChatSessionUser contactSessionUser = new ChatSessionUser();
            contactSessionUser.setUserId(contactId);
            contactSessionUser.setContactId(applyUserId);
            contactSessionUser.setSessionId(sessionId);
            UserInfo applyUserInfo = userInfoDao.queryById(applyUserId);
            contactSessionUser.setContactName(applyUserInfo.getNickName());
            chatSessionUsers.add(contactSessionUser);
            chatSessionUserDao.insertOrUpdateBatch(chatSessionUsers);

            //记录消息表
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setSessionId(sessionId);
            chatMessage.setMessageType(MessageTypeEnum.ADD_FRIEND.getType());
            chatMessage.setMessageContent(applyInfo);
            chatMessage.setSendUserId(applyUserId);
            chatMessage.setSendUserNickName(applyUserInfo.getNickName());
            chatMessage.setSendTime(curDate.getTime());
            chatMessage.setContactId(contactId);
            chatMessage.setContactType(UserContactTypeEnum.USER.getType());

            MessageSendDto messageSendDto = new MessageSendDto();
            BeanUtils.copyProperties(chatMessage,messageSendDto);
            //发送给接受好友申请的人
            messageHandler.sendMessage(messageSendDto);

            //发送给申请人，发送人就是接受人，联系人就是申请人
            messageSendDto.setMessageType(MessageTypeEnum.ADD_FRIEND_SELF.getType());
            messageSendDto.setContactId(applyUserId);
            messageSendDto.setExtendData(contactUser);
            messageHandler.sendMessage(messageSendDto);
        }else {
            //加入群组
            ChatSessionUser chatSessionUser = new ChatSessionUser();
            chatSessionUser.setUserId(applyUserId);
            chatSessionUser.setContactId(contactId);
            GroupInfo groupInfo = groupInfoDao.selectByGroupId(contactId);
            chatSessionUser.setContactName(groupInfo.getGroupName());
            chatSessionUser.setSessionId(sessionId);
            chatSessionUserDao.insertOrUpdate(chatSessionUser);


            UserInfo applyUserInfo = userInfoDao.queryById(applyUserId);
            String sendMessage = String.format(MessageTypeEnum.ADD_GROUP.getInitMessage(),applyUserInfo.getNickName());

            //增加session信息
            ChatSession chatSession = new ChatSession();
            chatSession.setSessionId(sessionId);
            chatSession.setLastReceiveTime(curDate.getTime());
            chatSession.setLastMessage(sendMessage);
            chatSessionDao.insertOrUpdate(chatSession);

            //增加聊天消息
            ChatMessage chatMessage = new ChatMessage();
            chatMessage.setSessionId(sessionId);
            chatMessage.setMessageType(MessageTypeEnum.ADD_GROUP.getType());
            chatMessage.setMessageContent(sendMessage);
            chatMessage.setSendTime(curDate.getTime());
            chatMessage.setContactId(contactId);
            chatMessage.setContactType(UserContactTypeEnum.GROUP.getType());
            chatMessage.setStatus(MessageStatusEnum.SENDED.getStatus());
            chatMessageDao.insert(chatMessage);

            //将群组添加到联系人
            redisComponent.addUserContact(applyUserId,groupInfo.getGroupId());

            //将联系人channel添加到群组channel
            channelContextUtils.addUser2Group(applyUserId,groupInfo.getGroupId());

            //发送群消息
            MessageSendDto messageSendDto = new MessageSendDto();
            BeanUtils.copyProperties(chatMessage,messageSendDto);
            messageSendDto.setContactId(contactId);

            //获取群人数
            UserContact queryUserContact = new UserContact();
            queryUserContact.setContactId(contactId);
            queryUserContact.setStatus(UserContactStatusEnum.FRIEND.getStatus());
            long memberCount = userContactDao.count(queryUserContact);
            messageSendDto.setMemberCount((int) memberCount);
            messageSendDto.setContactName(groupInfo.getGroupName());
            //发送消息
            messageHandler.sendMessage(messageSendDto);


        }

    }
}
